package com.cisystem.system.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.*;

import com.alibaba.excel.EasyExcel;
import com.cisystem.common.config.CiSystemConfig;
import com.cisystem.common.exception.base.BaseException;
import com.cisystem.common.utils.DateUtils;
import com.cisystem.common.utils.StringUtils;
import com.cisystem.common.utils.excel.ExcelDataListener;
import com.cisystem.common.utils.file.FileUtils;
import com.cisystem.common.utils.uuid.IdUtils;
import com.cisystem.system.domain.FileDir;
import com.cisystem.common.utils.excel.ExcelFileData;
import com.cisystem.system.mapper.FileDirMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.cisystem.system.mapper.FileStoreMapper;
import com.cisystem.system.domain.FileStore;
import com.cisystem.system.service.IFileStoreService;
import org.springframework.util.CollectionUtils;

/**
 * 文件数据Service业务层处理
 *
 * @author xxx
 * @date 2024-07-31
 */
@Service
public class FileStoreServiceImpl implements IFileStoreService {
    @Autowired
    private FileStoreMapper fileStoreMapper;

    @Autowired
    private FileDirMapper fileDirMapper;

    /**
     * 查询文件数据
     *
     * @param id 文件数据主键
     * @return 文件数据
     */
    @Override
    public FileStore selectFileStoreById(String id) {
        return fileStoreMapper.selectFileStoreById(id);
    }

    /**
     * 查询文件数据列表
     *
     * @param fileStore 文件数据
     * @return 文件数据
     */
    @Override
    public List<FileStore> selectFileStoreList(FileStore fileStore) {
        return fileStoreMapper.selectFileStoreList(fileStore);
    }

    /**
     * 新增文件数据
     *
     * @param fileStore 文件数据
     * @return 结果
     */
    @Override
    public int insertFileStore(FileStore fileStore) {
        fileStore.setCreateTime(DateUtils.getNowDate());
        return fileStoreMapper.insertFileStore(fileStore);
    }

    /**
     * 修改文件数据
     *
     * @param fileStore 文件数据
     * @return 结果
     */
    @Override
    public int updateFileStore(FileStore fileStore) {
        fileStore.setUpdateTime(DateUtils.getNowDate());
        return fileStoreMapper.updateFileStore(fileStore);
    }

    /**
     * 批量删除文件数据
     *
     * @param ids 需要删除的文件数据主键
     * @return 结果
     */
    @Override
    public int deleteFileStoreByIds(String[] ids) {
        return fileStoreMapper.deleteFileStoreByIds(ids);
    }

    /**
     * 删除文件数据信息
     *
     * @param id 文件数据主键
     * @return 结果
     */
    @Override
    public int deleteFileStoreById(String id) {
        return fileStoreMapper.deleteFileStoreById(id);
    }

    /**
     * 同步文件,将配置文件中的文件同步到数据库
     * 同时将文件复制到备份目录
     */
    @Override
    public void syncFileStore(){
        syncFile("dcc",CiSystemConfig.getDccPath());
        syncFile("first",CiSystemConfig.getFirstPath());
    }
    private void syncFile(String type,String filePath){
        List<FileStore> fileStores = new ArrayList<>();
        List<FileDir> fileDirs = new ArrayList<>();
        try {
            String fatherId = "0";
            Map<String, Object> subMap = new HashMap<>();
            subMap.put("files", new ArrayList<String>());
            subMap.put("dir", new ArrayList<HashMap<String, Object>>());
            subMap.put("path", filePath);
            // 递归读取path下的所有文件
            FileUtils.readFile(subMap);
            // 过滤已经存在的文件
            String search = "";
            List<ExcelFileData > list  = new ArrayList<>();
            if ("dcc".equals(type)){
                search = filePath.replace(CiSystemConfig.getDccPath(),CiSystemConfig.getCopyDccPath()).replace("\\","\\\\");
            }else{
                search = filePath.replace(CiSystemConfig.getFirstPath(),CiSystemConfig.getCopyFirstPath()).replace("\\","\\\\");
                EasyExcel.read(CiSystemConfig.getFirstExcelPath(), ExcelFileData.class, new ExcelDataListener(list)).sheet().doRead();
            }
            List<FileStore> fileStoreList = fileStoreMapper.selectFileStoreListByFilePathBegin(search);
            // 过滤已经存在的文件夹
            List<FileDir> fileDirList = fileDirMapper.selectFileDirList(new FileDir());
            if (CollectionUtils.isEmpty(fileStoreList)){
                fileStoreList = new ArrayList<>();
            }
            if (CollectionUtils.isEmpty(fileDirList)){
                fileDirList = new ArrayList<>();
            }
            // 过滤文件，如果存在filesStores和fileDirs为空则不进行插入
            loadFile(list,type,fileStoreList,fileDirList,fileStores,fileDirs,subMap,fatherId);
            if (!CollectionUtils.isEmpty(fileStores)){
                fileStoreMapper.batchInsertFileStore(fileStores);
            }
            if (!CollectionUtils.isEmpty(fileDirs)){
                fileDirMapper.batchInsertFileDir(fileDirs);
            }
            if ("first".equals(type) && !list.isEmpty()){
                Map<String,String> snMap = new HashMap<>();
                // 找出所有的最高版本的记录
                for (ExcelFileData excelFileData : list) {
                    String sn = excelFileData.getSn();
                    String version = excelFileData.getVersion();
                    if (snMap.containsKey(sn)) {
                        String oldVersion = snMap.get(sn);
                        if (StringUtils.isNotEmpty(oldVersion) && StringUtils.isNotEmpty(version)){
                            String versionn =  version.replace("V","").replace("v","").replace(".","");
                            String oldVersionn = oldVersion.replace("V","").replace("v","").replace(".","");
                            if (versionn.compareTo(oldVersionn) > 0) {
                                snMap.put(sn, version);
                            }
                        }
                    } else {
                        snMap.put(sn, version);
                    }
                }
                // 更改所有相同sn的文件为最高版本对应的名称
                List<String> snList1 = new ArrayList<>(snMap.keySet());
                List<FileStore> allBySN =null;
                if (!snList1.isEmpty()){
                    allBySN = fileStoreMapper.findAllBySN(snList1);
                }
                for (ExcelFileData excelFileData : list) {
                    String sn = excelFileData.getSn();
                    if (!CollectionUtils.isEmpty(allBySN) && sn != null){
                        for (FileStore fileStore : allBySN) {
                            if (fileStore.getFileName() != null && fileStore.getFileName().startsWith(sn)){
                                fileStore.setRemarkName(excelFileData.getFileName());
                                fileStore.setFileVersion(excelFileData.getVersion());
                                fileStoreMapper.updateFileStore(fileStore);
                            }
                        }
                    }
                }

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<FileStore> listAllByDirectory(FileStore fileStore) {
        return fileStoreMapper.listAllByDirectory(fileStore);
    }

    @Override
    public List<FileStore> getAllByDirIds(List<String> childDirIds) {
        if (CollectionUtils.isEmpty(childDirIds)){
            return new ArrayList<>();
        }
        return fileStoreMapper.getAllbyDirIds(childDirIds);
    }

    @Override
    public void editVisible(String fileId, String visible) {
        if (StringUtils.isEmpty(fileId) ||  (!"n".equals(visible) && !"y".equals(visible))){
            throw new BaseException("参数错误");
        }
        FileStore fileStore = fileStoreMapper.selectFileStoreById(fileId);
        if (fileStore == null){
            throw new BaseException("文件不存在");
        }
        fileStore.setVisible(visible);
        fileStoreMapper.updateFileStore(fileStore);
    }

    @Override
    public List<FileStore> listAllByFileIds(List<String> fileids) {
        if (!CollectionUtils.isEmpty(fileids)){
            return fileStoreMapper.listAllByFileIds(fileids);
        }
        return new ArrayList<>();
    }

    /**
     * 分析所有文件
     */
    private void loadFile(List<ExcelFileData > list ,String type ,List<FileStore> oldFileStores,List<FileDir> oldFileDirs ,List<FileStore> fileStores,List<FileDir> fileDirs ,Map<String,Object> map,String dirFatherId) throws IOException {
        String copyDccFilePath ;
        String dccFilePath ;
        if ("dcc".equals(type)){
             copyDccFilePath = CiSystemConfig.getCopyDccPath();
             dccFilePath = CiSystemConfig.getDccPath();
        }else{
            copyDccFilePath = CiSystemConfig.getCopyFirstPath();
            dccFilePath = CiSystemConfig.getFirstPath();
        }
        Date date = new Date();
        String dateVersion;
        // 获取当前目录下的所有文件
        List<String> files =(List<String>) map.get("files");
        // 获取当前目录下所有文件夹
        List<Map<String, Object>> dir = (List<Map<String, Object>>) map.get("dir");
        // 当前目录的路径
        String filepath = (String) map.get("path");
        String simpleUUID;
        // 生成当前文件夹的唯一id
        String dirId = IdUtils.simpleUUID();
        // filePath为全路径，获取文件名称
        String dirName = filepath.substring(filepath.lastIndexOf("\\")+1);
        // 替换读取的文件路径  替换为需要复制的路径
        String copyDirPath = filepath.replace(dccFilePath,copyDccFilePath);
        // 组合文件夹的唯一key。文件名+路径，用于判断是否存在
        String fileDirkey = dirName+"*-*"+copyDirPath;
        // 查找是否有相同的文件夹存在
        FileDir fileDir = oldFileDirs.stream().filter(i -> fileDirkey.equals(i.getFolderName() + "*-*" + i.getFolderPath())).findAny().orElse(null);
        // 没有相同的文件夹则新建
        if (fileDir == null){
            fileDir = new FileDir();
            // 设置当前文件夹的唯一id
            fileDir.setId(dirId);
            fileDir.setFolderName(dirName);
            // 替换复制的路径
            fileDir.setFolderPath(copyDirPath);
            fileDir.setFartherId(dirFatherId);
            fileDir.setCreateBy("ADMIN");
            fileDir.setUpdateBy("ADMIN");
            fileDir.setCreateTime(date);
            fileDir.setUpdateTime(date);
            fileDirs.add(fileDir);
        }else{
            // 如果存在获取当前文件夹的唯一id
            dirId = fileDir.getId();
        }
        // 当前文件夹下的文件
        if (!CollectionUtils.isEmpty(files)){
            // 遍历每个文件
            for (String file : files) {
                // 当前时间的时间戳
                dateVersion = DateUtils.dateTimeNow();
                // file为文件的全路径，替换掉配置文件中的路径
                file = file.replace(filepath+"\\","");
                file = file.replace(filepath,"");
                // 替换当前文件夹的路径 替换为需要复制的路径
                String copyFilePath = filepath.replace(dccFilePath,copyDccFilePath);
                // 文件全路径出去配置文件中配置的路径
                String originName = file;

                String[] split = file.split("\\.");
                StringBuffer fileName = new StringBuffer();
                // 文件名称增加时间戳，暂时舍去
                if (split.length>1){
                    for (int i = 0; i < split.length-1; i++) {
                        fileName.append(split[i]);
                    }
                }
                file = fileName.append(".").append(split[split.length-1]).toString();
                // 生成文件唯一id
                simpleUUID = IdUtils.simpleUUID();
                // 文件唯一key。文件名+路径，用于判断是否存在
                String filekey = originName+"*-*"+copyFilePath;
                // 查找是否有相同的文件存在
                FileStore fileStore = oldFileStores.stream().filter(i -> filekey.equals(i.getFileOriginName() + "*-*" + i.getFilePath())).findAny().orElse(null);
                // 没有相同的文件则新建
                if (fileStore == null) {
                    fileStore = new FileStore();
                    if ("first".equals(type) && !CollectionUtils.isEmpty(list)){
                        for (ExcelFileData excelFileData : list) {
                            String sn = excelFileData.getSn();
                            String version = excelFileData.getVersion();
                            String name = sn+"("+version+")";
                            if (name.equals(originName.replace("."+split[split.length-1],""))){
                                fileStore.setRemarkName(excelFileData.getFileName());
                                fileStore.setFileVersion(version);
                                break;
                            }
                        }
                    }
                    if (fileStore.getFileVersion() == null){
                        fileStore.setFileVersion("");
                    }
                    fileStore.setFileOriginName(originName);
                    fileStore.setId(simpleUUID);
                    fileStore.setFileName(file);
                    // 当前文件夹的 复制的路径
                    fileStore.setFilePath(copyFilePath);
                    fileStore.setFileOriginId(simpleUUID);
                    fileStore.setCreateBy("ADMIN");
                    fileStore.setUpdateBy("ADMIN");
                    fileStore.setCreateTime(date);
                    fileStore.setUpdateTime(date);
                    fileStore.setFileDir(0);
                    fileStore.setRemark("自动同步");
                    fileStore.setDirId(dirId);
                    fileStore.setFileType(type);
                    fileStore.setVisible("y");
                    fileStores.add(fileStore);
                    // 复制文件到备份目录
                    FileUtils.copyFile(new File(filepath+"\\"+originName),copyFilePath);
                }
            }
        }
        // 如果当前文件夹存在子文件夹。则递归处理子文件夹
        if (!CollectionUtils.isEmpty(dir)){
            for (Map<String, Object> subMap : dir) {
                loadFile(list,type,oldFileStores,oldFileDirs,fileStores,fileDirs,subMap,dirId);
            }
        }
    }
}
